# -*- coding: utf-8 -*-

import time
import sys, string
import re

from epguide.data_formats import Channel, Event, ChannelDict
from lxml import etree

XMLTV_RE = re.compile('[^\w\d]', re.IGNORECASE | re.UNICODE)

XMLTV_DECLARATION = """<?xml version="1.0"?>
<!DOCTYPE tv SYSTEM "xmltv.dtd">
<tv/>"""

event_format="""
<programme start="%s %s" %schannel="%s">
  <title>%s</title>
  <sub-title>%s</sub-title>
  <desc>%s</desc>
  <category>%s</category>
</programme>\n 
"""

channel_format="""<channel id="%s"><display-name lang="pl">%s</display-name></channel>\n"""

class XmltvOutput(object):
    """
    klasa wyjscia w formacie XMLTV
    """
    
    def __init__(self, config):
        self.file = None
        self.config = config
        self.channel_list = None

        # strefa czasowa aktualna
        if time.localtime(time.time()).tm_isdst and time.daylight:
            self.tz = time.altzone /60 /60
        else:
            self.tz = time.timezone /60 /60

        if self.tz > 0:
            sign = "-" # zmieniamy znak bo to roznica DO UTC (a nie od)
        else:
            sign = "+"
        self.tz = "%s0%s00" % (sign, abs(self.tz))

    
    def Init(self):
        """
        inicjalizacja wyjscia
        """
        if self.config.options.filename is not None:
            self.file = open(self.config.options.filename   , "w+")
        else:
            self.file = sys.stdout
        
        self.xml = etree.fromstring(XMLTV_DECLARATION)
        self.xml.set('generator-info-name', 'epguide')
        self.xml.set('generator-info-url', 'http://code.google.com/r/epguide/')
            
    def Finish(self):
        """
        zamkniecie wyjscia
        """
        et = etree.ElementTree(self.xml)
        et.write(self.file, pretty_print=True, xml_declaration=True, encoding="UTF-8")
        self.file.close()

    def FormatString(self, txt):
        formatTxt = string.replace(txt, u"&", u"&amp;")
        formatTxt = string.replace(formatTxt, u"<", u"")
        formatTxt = string.replace(formatTxt, u">", u"")
        return formatTxt

    def SaveChannelList(self, channel_list):
        """
        zapisanie listy kanalow
        """
        self.xml.set('date', channel_list.date.strftime('%Y-%m-%d'))
        self.xml.set('source-info-name', channel_list.parser.info_name)
        self.xml.set('source-info-url', channel_list.parser.info_url)
        self.xml.set('source-data-url', channel_list.parser.data_url)
        i = 0
        for id, channel in channel_list.iteritems():
            ch = self.xml.makeelement('channel',
                                      {'id': ("%s.%s" % (XMLTV_RE.sub('', channel.name),
                                                         channel_list.parser.tag)).lower()
                                      })
            
            # nazwa kanału
            display_name = ch.makeelement('display-name')
            display_name.text = channel.name
            ch.append(display_name)
            if getattr(channel_list.parser, 'language', None):
                    display_name.set('lang', channel_list.parser.language)

            # numer kanału 
            if channel.number:
                display_name = ch.makeelement('display-name')
                display_name.text = str(channel.number)
                ch.append(display_name)

            if channel.icon_url:
                ch.append(ch.makeelement('icon', url=channel.icon_url))
                
            # kanały na początku
            self.xml.insert(i, ch)
            i += 1
            
    
    def SaveGuide(self, guide):
        """
        zapisanie programu
        """
        if len(guide) == 0:
            return

        if not self.channel_list:
            self.channel_list = ChannelDict(guide.parser)

        xmltv_id = ("%s.%s" % (XMLTV_RE.sub('', guide.channel.name), guide.parser.tag)).lower()
        parser_lang = getattr(guide.parser, 'language', None)

        if not guide.channel.id in self.channel_list:
            self.channel_list[guide.channel.id] = guide.channel

        for item in guide:
            xmltv_ns = None

            programme = self.xml.makeelement('programme',
                                             channel = xmltv_id,
                                             start = "%s %s" % (item.time_start.strftime("%Y%m%d%H%M%S"),
                                                                self.tz))
            
            if item.time_end:
                programme.set('end', "%s %s" % (item.time_start.strftime("%Y%m%d%H%M%S"),
                                                self.tz))

            for k, v in (('title', 'title'),
                         ('subtitle', 'sub-title'),
                         ('description', 'desc')):
                
                if getattr(item, k):
                    e = programme.makeelement(v)
                    e.text = getattr(item, k)
                    programme.append(e)
                    if parser_lang:
                        e.set('lang', parser_lang)

            if item.actors or item.directors:
                credits = programme.makeelement('credits')
                programme.append(credits)
            else:
                credits = None
            
            for e, t in {programme: (('categories', 'category', True),
                                     ('countries', 'country', True)),
                         credits:   (('actors', 'actor', False),
                                     ('directors', 'director', False))}.iteritems():

                for k, v, l in t:
                    if getattr(item, k, None):
                        for s in getattr(item, k):
                            p = e.makeelement(v)
                            p.text = s
                            e.append(p)
                            if l and parser_lang:
                                p.set('lang', parser_lang)
            
            if item.runtime:
                runtime = programme.makeelement('length', units='minutes')
                runtime.text = str(item.runtime)
                programme.append(runtime)
                
            if item.thumb_url:
                programme.append(programme.makeelement('icon', src=item.thumb_url))
            
            # numer odcinka w formacie xmltv-ns
            if item.episode and item.episode_count:
                xmltv_ns = '.%d/%d.' % \
                    (item.episode - 1,
                     item.episode_count)
            elif item.episode:
                xmltv_ns = '.%d.' % (item.episode - 1)
            if item.season:
                xmltv_ns = '%d%s' % (item.season - 1, xmltv_ns)

            if xmltv_ns:
                ns = programme.makeelement('episode-num', system='xmltv_ns')
                ns.text = xmltv_ns
                programme.append(ns)

            if item.properties:
                props = set(item.properties)

                if props.intersection(('hd', 'pano')):
                    video = programme.makeelement('video')
                    programme.append('video')
                    if 'hd' in props:
                        quality = video.makeelement('quality')
                        quality.text = 'HDTV'
                        video.append(quality)
                    if 'pano' in props:
                        aspect = video.makeelement('aspect')
                        aspect.text = '16:9'
                        video.append(quality)

                if props.intersection(('surr', 'dd51')):
                    audio = programme.makeelement('audio')
                    programme.append(audio)
                    stereo = audio.makeelement('audio')
                    audio.append(stereo)
                    if 'surr' in props:
                        stereo.text = 'surround'
                    elif 'dd51' in props:
                        stereo.text = 'dolby digital'

                if 'prem' in props:
                    premiere = programme.makeelement('premiere')
                    programme.append(premiere)
                    if parser_lang:
                        premiere.set('lang', parser_lang)

                age = list(props.intersection(('age3', 'age7', 'age12', 'age16'))) 
                if age:
                    rating = programme.makeelement('rating')
                    rating.text = age[0][3:]
                    programme.append(rating)

            self.xml.append(programme)

    def SaveGuideChannels(self):
        self.SaveChannelList(self.channel_list)
